<template>
  <div :class="[overflow == 'auto' ? 'a-tree' : '']">
    <div v-if="showInput" class="w-60 mb-2 showCon">
      <el-input
        v-model="filterText"
        style="width: 100% !important"
        :placeholder="placeholder"
        :clearable="clearable"
      />
      <el-button type="primary" v-if="showAddTree" @click="handleAddTree">
        <el-icon><Plus /></el-icon>
      </el-button>
      <slot name="addTree"></slot>
    </div>
    <div :class="[overflow == 'auto' && showInput ? 'tree-containerInput' : overflow == 'auto' && !showInput ? 'tree-container' : '']">
      <slot name="toggleAll"></slot>
      <el-tree
        ref="treeRef"
        :style="{ maxWidth: !maxWidth ? '600px' : maxWidth }"
        :class="[!isIcon ? 'customTree' : '']"
        :data="treeData"
        :props="defaultProps"
        :show-checkbox="showCheckbox"
        :node-key="nodeKey"
        :default-expanded-keys="defaultExpandedKeys"
        :default-checked-keys="defaultCheckedKeys"
        :default-expand-all="defaultExpandAll"
        :highlight-current="highlightCurrent"
        :filter-node-method="filterNode"
        :accordion="accordion"
        :expand-on-click-node="expandOnClickNode"
        :check-strictly="checkStrictly"
        :empty-text="emptyText"
        :current-node-key="currentNodeKey"
        @node-click="handleNodeClick"
        @check-change="handleCheckChange"
      >
        <template #default="{ node, data }">
          <!-- 自定义图标插槽 -->
          <el-icon
            class="customIcon"
            v-if="!isIcon"
            :style="{
              opacity:
                data[childrenKey] && data[childrenKey]?.length
                  ? 1
                  : childrenIcon && !data[childrenKey]?.length
                  ? 1
                  : 0,
            }"
          >
            <slot name="icon" :data="data"></slot>
          </el-icon>

          <div class="custom-tree-node">
            <!-- 图标为自定义的时候使用的是文本点击的触发方法 -->
            <span
              class="label"
              v-if="!isIcon && !customLabel"
              @click.stop="handleLabelClick(data, node)"
            >
              <el-text v-if="!customNode" :truncated="truncated">{{
                node.label
              }}</el-text>
              <slot
                v-else
                name="customLabelNode"
                :data="data"
                :node="node"
              ></slot>
            </span>
            <span class="label" v-if="!isIcon && customLabel">
              <el-text v-if="!customNode" :truncated="truncated">{{
                node.label
              }}</el-text>
              <slot
                v-else
                name="customLabelNode"
                :data="data"
                :node="node"
              ></slot>
            </span>
            <span class="label" v-if="isIcon">
              <el-text v-if="!customNode" :truncated="truncated">{{
                node.label
              }}</el-text>
              <slot
                v-else
                name="customLabelNode"
                :data="data"
                :node="node"
              ></slot>
            </span>
            <!-- 自定义操作栏 -->
            <slot name="treeMenu" :node="node" :data="data"></slot>
            <!-- isShowMenu 是否开启menu，启用自带的menu -->
            <div v-if="isShowMenu">
              <el-button type="primary" link @click.stop="append(data)">
                新增
              </el-button>
              <el-button
                style="margin-left: 4px"
                type="danger"
                link
                @click.stop="remove(node, data)"
              >
                删除
              </el-button>
            </div>
          </div>
        </template>
      </el-tree>
    </div>
  </div>
</template>

<script lang="ts" setup>
const props = defineProps({
  modelValue: {
    type: Array,
    default: [
      {
        id: 1,
        label: "Level one 1",
        children: [
          {
            id: 4,
            label: "Level two 1-1",
            children: [
              {
                id: 9,
                label: "Level three 1-1-1",
              },
              {
                id: 10,
                label: "Level three 1-1-2",
              },
            ],
          },
        ],
      },
      {
        id: 2,
        label: "Level one 2",
        children: [
          {
            id: 5,
            label: "Level two 2-1",
          },
          {
            id: 6,
            label: "Level two 2-2",
          },
        ],
      },
      {
        id: 3,
        label: "Level one 3",
        children: [
          {
            id: 7,
            label: "Level two 3-1",
          },
          {
            id: 8,
            label: "Level two 3-2",
          },
        ],
      },
    ],
  },
  nodeKey: {
    type: String,
    default: "id",
  },
  showCheckbox: {
    type: Boolean,
    default: false,
  },
  defaultExpandedKeys: {
    type: Array,
    default: [],
  },
  defaultCheckedKeys: {
    type: Array,
    default: [],
  },
  defaultProps: {
    type: Object,
    default: {
      children: "children",
      label: "label",
    },
  },
  maxWidth: {
    type: String,
    default: "",
  },
  defaultExpandAll: {
    type: Boolean,
    default: false,
  },
  highlightCurrent: {
    type: Boolean,
    default: false,
  },
  clearable: {
    type: Boolean,
    default: false,
  },
  accordion: {
    type: Boolean,
    default: false,
  },
  expandOnClickNode: {
    type: Boolean,
    default: true,
  },
  showInput: {
    type: Boolean,
    default: false,
  },
  isShowMenu: {
    type: Boolean,
    default: false,
  },
  checkStrictly: {
    type: Boolean,
    default: false,
  },
  isIcon: {
    type: Boolean,
    default: true,
  },
  childrenIcon: {
    type: Boolean,
    default: false,
  },
  emptyText: {
    type: String,
    default: "暂无数据",
  },
  placeholder: {
    type: String,
    default: "请输入",
  },
  showAddTree: {
    type: Boolean,
    default: true,
  },
  customLabel: {
    type: Boolean,
    default: false,
  },
  currentNodeKey: [String, Number],
  overflow: {
    type: String,
    default: "",
  },
  truncated: {
    type: Boolean,
    default: false,
  },
  customNode: {
    type: Boolean,
    default: false,
  },
});

const {
  modelValue,
  defaultProps,
  showCheckbox,
  nodeKey,
  defaultExpandedKeys,
  defaultCheckedKeys,
  maxWidth,
  defaultExpandAll,
  highlightCurrent,
  clearable,
  accordion,
  expandOnClickNode,
  showInput,
  isShowMenu,
  checkStrictly,
  isIcon,
  emptyText,
  placeholder,
  showAddTree,
  customLabel,
  currentNodeKey,
  overflow,
  truncated,
  customNode,
  childrenIcon,
} = toRefs(props);
const emit = defineEmits();
const filterText = ref("");
const childrenKey = defaultProps.value?.children
  ? defaultProps.value?.children
  : "children";
const labelKey = defaultProps.value?.label
  ? defaultProps.value?.label
  : "label";
const treeRef = ref();

const treeData = computed({
  get() {
    return modelValue.value;
  },
  set(value) {
    emit("update:modelValue", value);
  },
});

watch(filterText, (val) => {
  treeRef.value!.filter(val);
});

const filterNode = (value, data) => {
  if (!value) return true;
  return data[labelKey].includes(value);
};

function handleNodeClick(data, node) {
  emit("handleNodeClick", data, node);
}

function handleLabelClick(data, node) {
  emit("handleLabelClick", data, node);
}

function handleCheckChange(data, checked, indeterminate) {
  emit("handleCheckChange", data, checked, indeterminate);
}

function append(data) {
  emit("append", data);
}
function remove(node, data) {
  emit("remove", node, data);
}

function handleAddTree() {
  emit("handleAddTree");
}

onMounted(() => {
  // 根据默认的选中的数据控制全选反选的状态
  if (defaultCheckedKeys.value.length) {
    handleCheckChange(treeRef.value.getCheckedNodes(), true, false);
  }
});

defineExpose({
  treeRef,
  handleNodeClick,
  handleCheckChange,
  append,
  remove,
  handleAddTree,
  handleLabelClick,
});
</script>

<style lang="scss" scoped>
.w-60 {
  width: 300px !important;
}
.mb-2 {
  margin-bottom: 20px;
}
.a-tree {
  height: 100%;
  .tree-containerInput {
    height: calc(100% - 52px);
    overflow: auto;
  }
  .tree-container {
    height: 100%;
    overflow: auto;
  }
}
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.customTree {
  :deep(.el-tree-node__expand-icon) {
    display: none;
  }
  .customIcon {
    margin: 0 6px;
  }
  .label {
    display: block;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    z-index: 999;
  }

  :deep(.el-tree-node__content) {
    .el-icon {
      order: 1;
    }
    .el-checkbox {
      order: 2;
    }
    .custom-tree-node {
      width: 100%;
      height: 100%;
      order: 3;
    }
  }
}
.showCon {
  display: flex;
}
</style>